05. Updating State

Let's step back one more time and think about what Redux is all about. The whole goal of Redux is to increase predictability:

Redux is a predictable state container for JavaScript apps.

With this in mind, let's see dig into how we can use actions and our state tree to predictably manage an application's state.

Predictable Functions

And we've got our second rule!

The function that returns the new state needs to be a pure function.

So far, our rules are:

  1. Only an event can change the state of the store.
  • The function that returns the new state needs to be a pure function.

A pure function can be a bit theoretical, so we'll take it step by step and explain why a pure function is so powerful and how it helps improve predictability.

Pure Functions

What are Pure Functions?

Pure functions are integral to how state in Redux applications is updated. By definition, pure functions:

  1. Return the same result if the same arguments are passed in
  • Depend solely on the arguments passed into them
  • Do not produce side effects, such as API requests and I/O operations

Let’s check out an example of a pure function, square():

// `square()` is a pure function

const square = x => x * x;

square() is a pure function because it outputs the same value every single time, given that the same argument is passed into it. There is no dependence on any other values to produce that result, and we can safely expect just that result to be returned -- no side effects (more on this in a bit!).

On the other hand, let’s check out an example of an impure function, calculateTip():

// `calculateTip()` is an impure function

const tipPercentage = 0.15;

const calculateTip = cost => cost * tipPercentage;

calculateTip() calculates and returns a number value. However, it relies on a variable (tipPercentage) that lives outside the function to produce that value. Since it fails one of the requirements of pure functions, calculateTip() is an impure function. However, we could convert this function to a pure function by passing in the outside variable, tipPercentage, as a second argument to this function!

const calculateTip = (cost, tipPercentage = 0.15) => cost * tipPercentage;

Why Pure Functions Are Great

For our purposes, the most important feature of a pure function is that it's predictable. If we have a function that takes in our state and an action that occurred, the function should (if it's pure!) return the exact same result every single time.

You're going to be sick of this by the end ;-) but this course (and Redux!) are all about predictability!

Quiz: Pure Functions facts

What is true about pure functions? Check all that apply.

SOLUTION:
  • Pure functions do not rely on information other than the arguments passed in to them to generate an output.
  • Pure functions do not depend on external state.

Quiz: Is this Pure?

Which of the following are pure functions? Please check all that apply:

SOLUTION:
  • const add = (a, b) => (
        a + b
    );
  • const double = array => {
        let doubledArray = [];
        array.forEach(n => doubledArray.push(n * 2));
        return doubledArray;
    };

The Reducer Function

⚠️ Please, do not use default parameters in the following programming quiz. It will throw an error when evaluating the response and you'll not be able to get the correct answer.

Start Quiz:

/* Create A Reducer
 *
 * You need to create a reducer called "appReducer" that accepts two arguments:
 * - First, an array containing information about ice cream 
 * - Second, an object with a 'DELETE_FLAVOR' `type` key
 * (i.e., the object contains information to delete the flavor from the state)
 *
 * The action your reducer will receive will look like this:
 * { type: 'DELETE_FLAVOR', flavor: 'Vanilla' }
 *
 * And the initial state will look something like this (as such, refrain 
 * from passing in default values for any parameters!):
 * [{ flavor: 'Chocolate', count: 36 }, { flavor: 'Vanilla', count: 210 }];
*/

Dispatch

Create Store Dispatch

QUIZ QUESTION::

Match the following store methods with their role:

ANSWER CHOICES:



Functionality

Store Method

gets the current state

takes in functions that will be called when the state changes

the application's state

modifies the state

SOLUTION:

Functionality

Store Method

the application's state

modifies the state

gets the current state

takes in functions that will be called when the state changes

Identifying The Library Code

The new dispatch() method is pretty small, but is vital to our functioning store code. To briefly recap how the method functions:

  • dispatch() is called with an Action
  • the reducer that was passed to createStore() is called with the current state tree and the action…this updates the state tree
  • because the state has (potentially) changed, all listener functions that have been registered with the subscribe() method are called

Summary

In this section, we learned about a number of important points about Redux. We learned about pure functions, a Reducer function (which, itself, needs to be a pure function), dispatching changes in our store, and identifying which parts of our code are generic library code and which are specific to our app.